package zero.tech.games.mj.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import zero.tech.core.data.Resp;
import zero.tech.core.util.RandomUtil;
import zero.tech.core.work.WorkManager;
import zero.tech.games.common.BigCalSource;
import zero.tech.games.common.Code;
import zero.tech.games.logic.common.Room;
import zero.tech.games.logic.common.RoomCache;
import zero.tech.games.logic.data.RoomStatus;
import zero.tech.games.logic.data.res.ResReconnet;
import zero.tech.games.logic.util.LogicUtil;
import zero.tech.games.logic.util.PckUtil;
import zero.tech.games.mj.data.MjBigPanel;
import zero.tech.games.mj.data.MjConfig;
import zero.tech.games.mj.data.MjGameBase;
import zero.tech.games.mj.data.MjRoomCache;
import zero.tech.games.mj.data.MjRoomStatus;
import zero.tech.games.mj.data.MjSmallPanel;
import zero.tech.games.mj.data.MjTimer;
import zero.tech.games.mj.data.consts.GameConst;
import zero.tech.games.mj.data.consts.MJCMD;
import zero.tech.games.mj.data.entity.Card;
import zero.tech.games.mj.data.entity.PlayerBigCal;
import zero.tech.games.mj.data.entity.PlayerData;
import zero.tech.games.mj.data.entity.PlayerSmallCal;
import zero.tech.games.mj.data.entity.SetcardsPanel;
import zero.tech.games.mj.data.notify.NotifyGameStart;
import zero.tech.games.mj.data.notify.NotifyGetCard;
import zero.tech.games.mj.data.notify.NotifyOutCard;
import zero.tech.games.mj.data.res.ResOutCard;
import zero.tech.games.mj.service.api.IMjService;
import zero.tech.games.mj.util.CardUtil;
import zero.tech.games.mj.util.GameLogic;
import zero.tech.games.mj.util.GameUtils;
import zero.tech.games.mj.util.PackageUtil;
import zero.tech.games.mj.util.PlaybackUtil;
import zero.tech.games.mj.util.RoomUtil;
import zero.tech.games.mj.work.sync.GameOverCalculateSyncWork;
import zero.tech.wsnet.controller.LogicController;
import zero.tech.wsnet.data.Message;

@Service
public class MjServiceImpl implements IMjService{
	
	private static final Logger logger = LoggerFactory.getLogger(MjServiceImpl.class);
	
	/**
	 * 中途恢复
	 */
	@Override
	public ResReconnet roomReconnect(Room room, LogicController online) {
		ResReconnet resReconnet=PackageUtil.packageResPdkReconnect(room,online);
		return resReconnet;
	}

	/**
	 * 开始游戏
	 */
	@Override
	public void gameStart(Room room) {
		// TODO Auto-generated method stub
		logger.info("房间号：{}，游戏开始======================-----------", room.getRoom_id());
		//初始数据
		initGameBase(room);
		//定庄
		choseBanker(room);
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjTimer mjTimer = (MjTimer) room.getTimer();
		//初始化小结算面板
		initSmallPanel(room);
		//发牌
		faPai(room);
		//改变打牌状态
		room.setRoom_status(MjRoomStatus.DA_PAI);
		mjTimer.updateLastTimer();
		// 发送手牌数据
		for (PlayerData player : gameBase.getPlayerMap().values()) {
			LogicController controller = player.getController(room);
			NotifyGameStart packageNotifyGameStart = PackageUtil.packageNotifyGameStart(room, player);
			controller.getWebClient().sendMessage(Message.build(
					MJCMD.NOTIFY_GAME_START, Resp.build(Code.OK, "通知游戏开始",packageNotifyGameStart)));
		}
		//开始打牌
		PlayerData ctrlVo = gameBase.getOperData();
		GameLogic.checkSelfCtrl(ctrlVo, ctrlVo.getCurrCard(), true, true, room);
	}
	
	/**
	 * 初始化小结算面板
	 * @param room
	 */
	private void initSmallPanel(Room room) {
		MjRoomCache roomCache = (MjRoomCache) room.getRoomCache();
		int room_times = room.getRoom_times();
		String room_id = room.getRoom_id();
		String configStr = room.getConfigStr();
		MjSmallPanel pdkSmallPanel = new MjSmallPanel();
		pdkSmallPanel.setRoom_id(room_id);
		pdkSmallPanel.setConfigStr(configStr);		
		roomCache.getSmallPanels().put(room_times, pdkSmallPanel);
	}
	
	/**
	 * 初始化GameBase
	 * @param room
	 */
	private void initGameBase(Room room) {
		MjConfig mjConfig =(MjConfig) room.getGameConfig();
		MjRoomCache roomCache = (MjRoomCache) room.getRoomCache();
		MjGameBase gameBase = new MjGameBase(room);
		gameBase.setMjConfig(mjConfig);
		room.setGameBase(gameBase);
		room.setRoom_status(RoomStatus.GAMING);
		room.setRoom_times(room.getRoom_times()+1);
		int gameType = gameBase.getMjConfig().getGameType();
		//初始化牌库
		if (gameType == 1) {
			//红中麻将
			gameBase.setCardBank(CardUtil.buildCards112(mjConfig.getHongZhongEight() == 1));
			gameBase.getGuiCards().add(196);
		} else {
			List<Integer> cards = CardUtil.buildCards108();
			gameBase.setCardBank(cards);
			if(gameType == 2) {
				// 翻鬼麻将
				gameBase.getGuiCards().add(cards.get(RandomUtil.randInt(cards.size() - 2)));
			}else if(gameType == 3) {
				// 双鬼麻将
				Integer integer = cards.get(RandomUtil.randInt(cards.size() - 2));
				gameBase.getGuiCards().add(integer);
				Integer integer2 = cards.get(RandomUtil.randInt(cards.size() - 2));
				while (CardUtil.isSameCard(integer, integer2)) {
					integer2 = cards.get(RandomUtil.randInt(cards.size() - 2));
				}
				gameBase.getGuiCards().add(integer2);
			}
		}
		//添加回放鬼牌数据
		gameBase.getPlaybackDetail().setGuiCards(gameBase.getGuiCards());
		//初始化大结算面板
		if(room.getRoom_times() == 1) {
			MjBigPanel bigPanel = new MjBigPanel();
			for (PlayerData temp : gameBase.getPlayerMap().values()) {
				LogicController controller = temp.getController(room);
				PlayerBigCal bigCal = new PlayerBigCal();
				bigCal.setSimpleUser(controller.getSimpleUser());
				bigPanel.getRoles().put(temp.getUid(), bigCal);
			}
			roomCache.setBigPanel(bigPanel);
		}
	}
	/**
	 * 定庄
	 * @param room
	 * @return
	 */
	private void choseBanker(Room room) {
		//第一局随机一名玩家做庄家，以后的牌局由上把第一个胡牌的玩家坐庄，如果第一炮为一炮多响则点炮玩家为下一轮庄家。
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjRoomCache extendCache = (MjRoomCache) room.getRoomCache();
		if (room.getRoom_times() == 1) {
			List<Integer> uids = new ArrayList<Integer>(gameBase.getPlayerMap().keySet());
			Collections.shuffle(uids);
			extendCache.setNextHostUid(uids.get(0));
		}
		int nextHostUid = extendCache.getNextHostUid();
		//设置当前操作玩家
		gameBase.setOperData(gameBase.getPlayerMap().get(nextHostUid));
		//设置当局庄家id
		gameBase.setHuid(nextHostUid);
	}
	
	/**
	 * 发牌,掷骰子
	 */
	public void faPai(Room room) {
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjRoomCache roomCache = (MjRoomCache) room.getRoomCache();
		SetcardsPanel setcardsPanel = roomCache.getSetcardsPanel();
		//获取玩家配牌器
		Map<Integer, List<Integer>> setsmap =setcardsPanel.getSetsmap();
		if(!setsmap.isEmpty()) {
			//根据配牌器发牌
			for(Entry<Integer,List<Integer>> entry : setsmap.entrySet()) {
				int uid = entry.getKey();
				//是否是房间游戏玩家
				if(gameBase.getPlayerMap().containsKey(uid)){
					List<Integer> cardIds = entry.getValue();
					//庄家14张，其他13张
					int cardNum = uid == gameBase.getHuid() ? 14 : 13;
					List<Integer> hands = CardUtil.findCardsByCardId(gameBase.getCardBank(), cardIds, cardNum);
					PlayerData playerData = gameBase.getPlayerUid(uid);
					playerData.setHandCard(hands);
					CardUtil.removeCardBank(gameBase.getCardBank(), hands);
				}
			}
			//检查玩家牌是否获取完毕，没获取完的补上
			for (PlayerData player : gameBase.getPlayerMap().values()) {
				//需要的牌 庄家14张，其他13张
				int cardNum = player.getUid() == gameBase.getHuid() ? 14 : 13;
				//需要补充的牌数量 （需要的牌 - 已经获取的手牌数量 = 补充的牌数）
				int repairNum = cardNum - player.getHandCard().size();
				for (int i = 0; i < repairNum; i++) {
					player.getHandCard().add(gameBase.getCardBank().remove(0));
				}
				//战绩用数据
				gameBase.getPlaybackDetail().getHandsmap().put(player.getUid(), player.getHandCard());
			}
		}else {
			//随机生成玩家手牌
			for (PlayerData player : gameBase.getPlayerMap().values()) {
				for (int i = 0; i < 13; i++) {
					player.getHandCard().add(gameBase.getCardBank().remove(0));
				}
				//庄家14张牌
				if (player.getUid() == gameBase.getHuid()) {
					player.getHandCard().add(gameBase.getCardBank().remove(0));
				}
				//战绩用数据
				gameBase.getPlaybackDetail().getHandsmap().put(player.getUid(), player.getHandCard());
			}
		}
		//设置庄家操作的牌
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (mvo.getUid() == gameBase.getHuid()) {
				mvo.setCurrCard(mvo.getHandCard().get(5));
				logger.info(mvo.getUid() + "---庄家手牌牌--" + mvo.getCurrCard());
				gameBase.updateCurrCtrl(mvo.getCurrCard(), mvo.getUid());
				//设置庄家可以打牌
				mvo.setOut(true);
			}
		}
	}
	
	/**
	 * 处理控制牌
	 */
	@Override
	public void reqCtrlCard(Room room, LogicController controller, String info, int type) {
		GameLogic.disposeReqCtrlCard(room, controller,info, type);
	}

	/**
	 * 处理出牌
	 */
	@Override
	public void reqOutCard(Room room, LogicController controller, int outCard) {
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjTimer mjTimer = (MjTimer) room.getTimer();
		PlayerData player = gameBase.getPlayerUid(controller.getId());
		boolean canOut = true;
		//是否有玩家正做特殊操作
		for (PlayerData playerData : gameBase.getPlayerMap().values()) {
			if (playerData.getUid() != player.getUid()) {
				if (playerData.getActionArr().size() > 0) {
					canOut = false;
					break;
				}
			}
		}
		if (room.getRoom_status() != MjRoomStatus.DA_PAI) {
			controller.getWebClient().sendMessage(
					Message.build(MJCMD.RES_OUT_CARD, Resp.build(Code.SERVER_ERROR, "不在出牌时间")));
			return;
		} else if (gameBase.getOperData().getUid() != player.getUid() || !player.isOut()) {
			controller.getWebClient().sendMessage(
					Message.build(MJCMD.RES_OUT_CARD, Resp.build(Code.SERVER_ERROR, "不在出牌位置")));
			return;
		} else if (!checkHaveCard(outCard, player.getHandCard(), gameBase.getGuiCards())) {
			controller.getWebClient().sendMessage(
					Message.build(MJCMD.RES_OUT_CARD, Resp.build(Code.SERVER_ERROR, "出牌不符合规则")));
			return;
		} else if (!canOut) {
			controller.getWebClient().sendMessage(
					Message.build(MJCMD.RES_OUT_CARD, Resp.build(Code.SERVER_ERROR, "请等待其他玩家操作")));
			return;
		}
		player.removeHandCard(outCard);
		ResOutCard builder = new ResOutCard();
		builder.setCards(player.getHandCard());
		controller.getWebClient().sendMessage(
				Message.build(MJCMD.RES_OUT_CARD, Resp.build(Code.OK, "出牌成功",builder)));
		// --------
		player.setOut(false);
		player.addOutCard(outCard);
		player.initActionArr();
		gameBase.updateCurrCtrl(outCard, player.getUid());
		gameBase.setGetCard(true);
		gameBase.setCurrOutId(player.getUid());
		gameBase.addOperPlayback(outCard + "_101_" + player.getUid() + "_" + gameBase.getCardBank().size());
		logger.info(" 出牌后打印日志 " + player.toString());
		mjTimer.updateLastTimer();
		NotifyOutCard packageNotifyOutCard = PackageUtil.packageNotifyOutCard(player, outCard);
		LogicUtil.broadRoomAllControllersInclude(room, Message.build(
				MJCMD.NOTIFY_OUT_CARD, Resp.build(Code.OK, "广播玩家打牌",packageNotifyOutCard)));
		int[] card2 = CardUtil.getCard(outCard);
		String[] tt = new String[] { "万", "条", "同" };
		logger.info("-------------" + outCard + "---------" + player.getNick() + "打牌 " + card2[1] + "-" + tt[card2[3]] + "------");
		// 重新排序手中的牌
		player.setHandCard(CardUtil.getNewList(player.getHandCard()));
		// --------------------------------------------------------------------------
		boolean isNoSp = GameLogic.checkSpCtrl(player, outCard, room);
		//让下一个玩家打牌
		if (isNoSp) {
			gameBase.setGangInfo(0, 0);
			gameBase.clearHuInfo();
			nextGetCard(false, room);
		}
	}

	/**
	 * 玩家拿牌的操作(起牌)
	 * @param isSelf
	 * @param room
	 */
	@Override
	public void nextGetCard(boolean isSelf, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjTimer mjTimer = (MjTimer) room.getTimer();
		MjConfig mjConfig = gameBase.getMjConfig();
		if (gameBase.getCardBank().isEmpty() || gameBase.getCardBank().size() <= flowBureau(mjConfig.getFanMaType())) {
			logger.info("流局了......................>>>>>>");
			gameOver(room);
			return;
		}
		if (gameBase.isGetCard() || isSelf) {
			mjTimer.setLastTimer(System.currentTimeMillis());// 更新倒计时
			gameBase.setGetCard(false);
			// 当前操作的玩家id
			int uid = isSelf ? gameBase.getOperData().getUid() : GameUtils.getNextPosByUid(room, gameBase.getOperData().getUid());
			PlayerData vo = gameBase.getPlayerUid(uid);
			gameBase.setPassInfo(uid, true);
			vo.setFanCount(0);
			int card = -1;
			card = getPai(gameBase);
			//card =244; //212  228  244 

			// 判断上局一炮多响强杠上炮有几个玩家胡拍，如果只有一个人抢，那么杠分就给他
			gameBase.setQiangGang(false);// 是不是抢杠
			gameBase.getHuArr().clear();// 当局可以胡的人
			gameBase.setHuCount(0);// 当局胡的人
			gameBase.getCanHu().clear();// 当局可以胡的人，不会变化的值
			gameBase.getHuList().clear();// 当局可以胡的人
			gameBase.setGangLast("");// 临时记录
			vo.setBuGang(false);
			gameBase.setHuSStr("");

			PlayerData self = null;
			for (PlayerData mvo : gameBase.getPlayerMap().values()) {
				LogicController user = mvo.getController(room);
				mvo.initActionArr();
				NotifyGetCard builder = new NotifyGetCard();
				builder.setUid(vo.getUid());// 用户ID
				builder.setLastNum(gameBase.getCardBank().size());// 牌库剩余牌
				builder.setOutCards(vo.getOutCard());// 玩家已出的牌
				builder.setCtrlArr(GameUtils.listStrToStringByl(vo.getCtrlCard()));// 玩家已操作的牌
				builder.setOperUid(gameBase.getOperData().getUid());
				builder.setCountDown(GameConst.DA_PAI_TIME);
				// 针对摸牌的玩家
				if (uid == mvo.getUid()) {
					vo.setOut(true);
					vo.addHandlCard(card);
					vo.setCurrCard(card);
					gameBase.updateCurrCtrl(card, uid);
					// 重新排序手中的牌
					vo.setHandCard(getNewList(vo.getHandCard()));
					self = mvo;
					builder.setCard(card);// 摸的牌
					builder.setCards(vo.getHandCard());// 玩家手牌
					gameBase.addOperPlayback(card + "_100_" + vo.getUid() + "_" + gameBase.getCardBank().size());
					logger.info(" 摸牌后打印日志 ", vo);
					int[] card2 = CardUtil.getCard(card);
					String[] tt = new String[] { "万", "条", "同" };
					 logger.info("----------------------" + vo.getNick() + "摸牌 " + card2[1] + "-" + tt[card2[3]] + "----------");
				} else {
					builder.setCard(0);// 摸的牌
					builder.setCards(new ArrayList<Integer>());// 玩家手牌

				}
				if (user != null) {
					user.getWebClient().sendMessage(Message.build(
							MJCMD.NOTIFY_GET_CARD, Resp.build(Code.OK, "通知玩家摸牌",builder)));
				}
			}

			if (self != null) {
				GameLogic.checkSelfCtrl(self, card, true, true, room);
			}
		}
	}
	
	/**
	 * 检测手中是否有这个牌
	 * 
	 * @param card
	 * @return
	 */
	private boolean checkHaveCard(int card, List<Integer> list, List<Integer> guiCards) {
		// 鬼牌不能打出去
		for (int i = 0; i < guiCards.size(); i++) {
			if (CardUtil.isSameCard(card, guiCards.get(i))) {
				return false;
			}
		}
		// 检查手里是否有这张牌
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i) == card) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 流局剩余牌数量
	 * 
	 * @param type
	 *            奖码数（0"",1"一码全中",2"",3"博码",4"4码",5"",6"6码"）
	 * @return 牌数量
	 */
	public int flowBureau(int type) {
		int num = 0;
		if (type == 1) {
			num = 1;
		} else if (type == 3) {
			num = 10;
		} else if (type == 4) {
			num = 4;
		} else if (type == 6) {
			num = 6;
		}
		return num;
	}
	
	/**
	 * 排序
	 * 
	 * @param list
	 * @return
	 */
	public List<Integer> getNewList(List<Integer> list) {
		List<Integer> arr = new ArrayList<Integer>();
		List<Card> clist = new ArrayList<Card>();
		for (int i = 0; i < list.size(); i++) {
			Card cvo = new Card();
			cvo.setCard(CardUtil.getCard(list.get(i)));
			clist.add(cvo);
		}
		// 处理顺序问题 顺序
		Collections.sort(clist, new Comparator<Card>() {
			public int compare(Card a, Card b) {
				int v = a.getType().compareTo(b.getType());
				if (v == 0) {
					return a.getPoint().compareTo(b.getPoint());
				}
				return v;
			}
		});

		// 重新包装
		for (int i = 0; i < clist.size(); i++) {
			arr.add(clist.get(i).getValue());
		}

		return arr;
	}
	
	/**
	 * 摸牌 th已修改
	 * @return
	 */
	public static int getPai(MjGameBase gameBase) {
		int card = gameBase.getCardBank().remove(0);
		return card;
	}
	
	public String getPai(List<Integer> arr) {
		String str = " ";
		String[] hua = new String[] { "万", "条", "筒", "字" };
		for (Integer integer : arr) {
			int[] car = CardUtil.getCard(integer);
			if (car[3] == 3) {
				if (car[1] == 1)
					str += "东 ";
				else if (car[1] == 2)
					str += "南 ";
				else if (car[1] == 3)
					str += "西 ";
				else if (car[1] == 4)
					str += "北 ";
				else if (car[1] == 5)
					str += "中 ";
				else if (car[1] == 6)
					str += "发 ";
				else if (car[1] == 7)
					str += "白 ";

			} else {
				str += car[1] + hua[car[3]] + " ";
			}
		}

		return str;
	}

	/**
	 * 准备开始结算
	 */
	@Override
	public void bigCalculate(Room room, int bigcalsource) {
		room.setRoom_status(RoomStatus.CALCULATING);
		WorkManager.getManager().submit(GameOverCalculateSyncWork.class,room,bigcalsource);		
	}
	
	/**
	 * 游戏结束
	 */
	@Override
	public void gameOver(Room room) {
		//小结算
		smallCalculate(room);
	}
	
	/**
	 * 小结算计算分数
	 * @param room
	 */
	private void smallCalculate(Room room) {
		// TODO Auto-generated method stub
		//计算中码
		getBoCode(room);
		//计算输赢
		countAllScore(room);
		//整理小结算面板
		smallCalScoreBegin(room);
		//发送小结算
		LogicUtil.broadRoomAllControllersInclude(room, Message.build(MJCMD.NOTIFY_SMALL_CALCULATE, Resp.build(Code.OK, "小结算数据",PckUtil.packageNotifySmallCalculate(room))));
		
		//检查是否有玩家的钱不够进行下一轮
		boolean advance_big_calculate=false;
		for(LogicController logicController:room.getAllControllers().values()) {
			boolean ok = RoomUtil.checkMoneyEnoughNextRound(room, logicController);
			if(!ok) {
				advance_big_calculate=true;
				break;
			}
		}
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		int total_times= gameBase.getMjConfig().getTotal_times();
		if(advance_big_calculate || room.getRoom_times() >= total_times) {
			bigCalculate(room,BigCalSource.SMALLOVER_BIG_CAL);
		}else {
			smallCalculateReset(room);
		}		
	}

	/**
	 * 切换等待下一局开始
	 * @param room
	 */
	private void smallCalculateReset(Room room) {
		PlaybackUtil.saveClubSmallPlayback(room);//临时保存小局战绩数据
		room.setRoom_status(RoomStatus.WAIT_NEXT_ROUND);
		RoomCache roomCache = room.getRoomCache();
		roomCache.getWatchers().clear();//清除观战者
		LogicUtil.broadRoomAllControllersInclude(room, Message.build(MJCMD.NOTIFY_SMALL_RESET, Resp.build(Code.OK, "小结算重置消息",PckUtil.packageNotifySmallReset(room))));
	}
	
	/**
	 * 计算中码
	 * @param room
	 */
	private void getBoCode(Room room) {
		logger.info("===中码统计===");
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjRoomCache extendCache = (MjRoomCache) room.getRoomCache();
		
		MjConfig mjConfig = gameBase.getMjConfig();
		int code = mjConfig.getFanMaType();
		String[] codeType = new String[] { "", "一码全中", "", "博码", "4码", "", "6码" };
		logger.info("===中码统计===类型：" + codeType[code]);
		boolean kg = false;
		for (PlayerData vo : gameBase.getPlayerMap().values()) {
			if (vo.isWin()) {
				kg = true;
				break;
			}
		}
		// 现在的 "", "一码全中", "", "博码", "4码", "", "6码"
		if (kg && ((code == 1 && gameBase.getCardBank().size() >= 1)
						|| (code == 3 && gameBase.getCardBank().size() >= 10)
						|| (code == 4 && gameBase.getCardBank().size() >= 4) 
						|| (code == 6 && gameBase.getCardBank().size() >= 6))) {
			// num 确定翻码牌张数
			int num = GameUtils.flowBureau(code);
			if (code == 3) {
				int hupai = gameBase.getHupai();
				if (CardUtil.isGuiPai(gameBase.getHupai(), gameBase.getGuiCards())) {
					num = 10;
				} else {
					int[] card = CardUtil.getCard(hupai);
					num = card[1];
				}
			}
			List<Integer> card = new ArrayList<Integer>();
			List<Integer> cards = gameBase.getCardBank();
			// 抓码牌
			if (cards.size() >= num) {
				for (int i = 0; i < num; i++) {
					if (cards.size() > 0) {
						card.add(cards.remove(0));
					}
				}
			}
			gameBase.setMaPai(card);

			// 处理翻码得分
			int maScore = 0;
			for (int i = 0; i < card.size(); i++) {
				Integer integer = card.get(i);
				// 一码全中
				if (code == 1) {
					// 鬼牌10分
					if (CardUtil.isGuiPai(integer, gameBase.getGuiCards())) {
						maScore += 10;
					} else {
						// 非鬼牌按点数算分
						int[] card2 = CardUtil.getCard(integer);
						maScore += card2[1];
					}
				} else {
					if (CardUtil.isGuiPai(integer, gameBase.getGuiCards())) {
						maScore += 1;
					} else {
						// 非鬼牌 1 5 9 算中码 +1
						int[] card2 = CardUtil.getCard(integer);
						if (card2[1] == 1 || card2[1] == 5 || card2[1] == 9) {
							maScore += 1;
						}
					}
				}
			}
			// 更新中码次数
			MjBigPanel bigPanel = (MjBigPanel) extendCache.getBigPanel();
			Set<Entry<Integer, PlayerBigCal>> entrySet = bigPanel.getRoles().entrySet();
			for (Entry<Integer, PlayerBigCal> entry : entrySet) {
				if (entry.getValue() != null) {
					PlayerBigCal value = entry.getValue();
					PlayerData player = gameBase.getPlayerMap().get(value.getSimpleUser().getUid());
					if (player != null) {
						if (player.isWin()) {
							value.setZhongMaTimes(value.getZhongMaTimes()
									+ maScore);
						}
					}
				}
			}

			maScore = maScore * mjConfig.getFanMaMulti();
			logger.info("游戏抓马类型{}_翻码倍数是{}__中码次数{}", code, mjConfig.getFanMaMulti(), maScore);
			gameBase.setTheCode(maScore);

			for (PlayerData vo : gameBase.getPlayerMap().values()) {
				if (vo.isWin()) {
					vo.setZhongMa(gameBase.getTheCode());
				}
			}
			// 更新中码得分
			for (PlayerData vo : gameBase.getPlayerMap().values()) {
				if (vo.isWin()) {
					int maLost = 0;
					boolean isZimo = false;
					for (PlayerData vo2 : gameBase.getPlayerMap().values()) {
						if (vo2.getHuType() == 7) {
							isZimo = true;
						}

					}
					for (PlayerData vo3 : gameBase.getPlayerMap().values()) {
						if (vo3.getUid() != vo.getUid() && isZimo) {
							// 每个输家输的码分
							vo3.setLose(vo3.getLose() + maScore);
							maLost += maScore;
						}else if(vo3.getUid() != vo.getUid() && vo3.isDianPao()){
							// 每个输家输的码分
							vo3.setLose(vo3.getLose() + maScore);
							maLost += maScore;
						}
					}
					// 赢家赢的码分
					vo.setWin(vo.getWin() + maLost);
				}
			}
		}
	}
	
	/**
	 * 统计玩家的积分
	 */
	private static void countAllScore(Room room){
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		for (PlayerData pvo : gameBase.getPlayerMap().values()) {
			if (!pvo.isWin()) {
				pvo.setHuType(GameConst.WIN_WEIHU);
			}
		}
		// 计算杠的得分-统计//三家人胡牌，剩一家没胡，最后一家也算杠分
		for (PlayerData vo : gameBase.getPlayerMap().values()) {
			countGangInfo(vo, room);
		}

		updatePlayerScore(room);
	}
	
	/**
	 * 计算杠分
	 * @param player
	 * @param room
	 */
	private static void countGangInfo(PlayerData player, Room room) {
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		int all = 0;
		logger.info(player.getNick() + " getGangArr:: " + player.getGangArr());
		if (player.getGangArr().size() > 0) {
			player.setGangStr("");
			for (int i = 0; i < player.getGangArr().size(); i++) {
				List<String> arr = GameUtils.getStrList(player.getGangArr().get(i),
						",");

				int type = GameUtils.getInteger(arr.get(arr.size() - 2));
				int score = GameUtils.getInteger(arr.get(arr.size() - 3));
				int roundCount = 0;
				String[] strArr = new String[] { "", "", "", "明杠", "", "暗杠",
						"点杠", "" };
				for (int j = 0; j < arr.size() - 3; j++) {
					int uid = GameUtils.getInteger(arr.get(j));
					PlayerData mvo = gameBase.getPlayerUid(uid);
					all += score;
					roundCount += score;
					mvo.setLose(mvo.getLose() + score);
					logger.info("【杠】输：" + mvo.getNick() + ":  当局:" + score
							+ "  总: " + mvo.getLose());
					logger.info("【统计】：" + mvo.getNick() + ":  win:"
							+ mvo.getWin() + "  lose: " + mvo.getLose());
				}
				// 通过转雨得到指向为自己的杠,跳过记录
				String[] split = arr.get(0).split(",");
				if (split.length == 1 && split[0].equals(player.getUid() + "")) {
					continue;
				}
				player.setGangStr(player.getGangStr() + " " + strArr[type] + "+" + roundCount);
			}
			if (all > 0) {
				player.setWin(player.getWin() + all);
				logger.info("【杠】赢：" + player.getNick() + " 当局:" + all + " 总：" + player.getWin());
			}
		}
	}

	/**
	 * 更新玩家分数
	 * @param room
	 */
	private static void updatePlayerScore(Room room){
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		// 计算玩家输赢
		for (PlayerData vo : gameBase.getPlayerMap().values()) {
			vo.setHuStr(GameUtils.getWinStr(vo, room));
			logger.info(vo.getHuStr());
			if (vo.isWin()) {
				int difen = vo.getDiFen();
				int all = 0;
				for (int i = 0; i < vo.getLoseArr().size(); i++) {
					PlayerData mvo = gameBase.getPlayerUid(vo.getLoseArr().get(i));
					int score = difen;
					all += score;
					mvo.setLose(mvo.getLose() + score);
					logger.info("【积分】输：" + mvo.getNick() + ":  当局:" + score + "  总: " + mvo.getLose());
					logger.info("【统计】：" + mvo.getNick() + ":  win:" + mvo.getWin() + "  lose: " + mvo.getLose());
				}
				vo.setWin(vo.getWin() + all);
				logger.info(vo.getWin() + "  " + vo.getLose());
				logger.info("【积分】赢：" + vo.getNick() + ": 当局:" + all + " 总:" + vo.getWin());
			}

		}
		// 押注倍数处理
		for (PlayerData controllerData : gameBase.getPlayerMap().values()) {
			controllerData.setWin(controllerData.getWin());
			controllerData.setLose(controllerData.getLose());
		}
		// 金币场不能输到负分
		int loseOutBoundCount = 0;
		int loseOutTemp = 0;
		int winOutBoundCount = 0;
		List<PlayerData> winList = new ArrayList<PlayerData>();
		for (PlayerData playerData : gameBase.getPlayerMap().values()) {
			LogicController lc = playerData.getController(room);
			long haveGold = lc.getGold();
			if (playerData.getWin() - playerData.getLose() > 0) {
				winOutBoundCount += (playerData.getWin() - playerData.getLose());
				winList.add(playerData);
			}
			if (playerData.getWin() - playerData.getLose() < haveGold * -1) {
				long loseOut = (playerData.getWin() - playerData.getLose() + haveGold) * -1;
				loseOutBoundCount += loseOut;
				loseOutTemp += loseOut;
				// 将输家的输分调整到携带的最大金币
				playerData.setLose(playerData.getLose() - loseOut);
			}
		}
		// 将超过携带金币的分数分配给赢家,确保被分后金币为0
		if (winList.size() == 1) {
			PlayerData cl = winList.get(0);
			cl.setWin(cl.getWin() - loseOutBoundCount);
		} else if (winList.size() > 1) {
			for (int i = 0; i < winList.size(); i++) {
				PlayerData controllerData = winList.get(i);
				if (i != winList.size()-1) {
					long userWin = controllerData.getWin() - controllerData.getLose();
					// 得到当前玩家扣金币比率
					double ratio = userWin / (winOutBoundCount * 1.0);
					int allot = (int) (loseOutBoundCount * ratio);
					loseOutTemp = loseOutTemp - allot;
					controllerData.setWin(controllerData.getWin() - allot);
				} else {
					controllerData.setWin(controllerData.getWin() - loseOutTemp);
				}
			}
		}
		logger.info("金币场:输超过携带金币的分数是{},赢家总赢分数是{},分配后剩余的分数是{}",loseOutBoundCount, winOutBoundCount, loseOutTemp);
		for (PlayerData controllerData : gameBase.getPlayerMap().values()) {
			controllerData.setGold(controllerData.getGold() + controllerData.getWin() - controllerData.getLose());
		}

	}
	
	
	/**
	 * 整理小结算面板
	 * @param room
	 */
	private void smallCalScoreBegin(Room room) {
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjRoomCache roomCache = (MjRoomCache) room.getRoomCache();
		MjBigPanel bigPanel = (MjBigPanel) roomCache.getBigPanel();
		long base_score = gameBase.getMjConfig().getBase_score();
		//设置小结算面板
		MjSmallPanel smallPanel = (MjSmallPanel) roomCache.getSmallPanels().get(room.getRoom_times());
		/** 当前局数 */
		smallPanel.setTimes(room.getRoom_times());
		/** 庄家ID */
		smallPanel.setHuid(gameBase.getHuid());
		/** 桌面剩余牌 */
		smallPanel.setLeftCards(gameBase.getCardBank());
		/** 当局码牌 */
		smallPanel.setMaCards(gameBase.getMaPai());
		/** 当局鬼牌 */
		smallPanel.setGuiCards(gameBase.getGuiCards());
		/** 是否流局 */
		smallPanel.setLiuJu(!GameUtils.checkHaveWin(gameBase));
		for (PlayerData player : gameBase.getPlayerMap().values()) {
			LogicController controller = player.getController(room);
			PlayerSmallCal smallCal = new PlayerSmallCal();
			smallCal.setSimpleUser(controller.getSimpleUser());
			smallCal.setCards(player.getHandCard());
			smallCal.setCtrlCards(GameUtils.listStrToStringByl(player.getCtrlCard()));
			smallCal.setOutCards(player.getOutCard());
			smallCal.setHuInfos(player.getHuType() + "_"
					+ (player.getHuCards().size() > 0 ? player.getHuCards().get(0) : -1) 
					+ "_" + player.getHuSort() + "_" + player.getHuStr());
			smallCal.setHostInfo(player.getUid() == gameBase.getHuid());
			smallCal.setTag("");
			smallCal.setFan(0);
			long score = (player.getWin() - player.getLose());
			smallCal.setWinScore(score * base_score);
			smallCal.setCurrentScore(controller.getGold());
			smallCal.setCur_win_gold(score * base_score);
			smallCal.setCur_win_score((int)score);
			smallPanel.getRoles().put(player.getUid(), smallCal);
			//记录玩家总输赢
			PlayerBigCal playerBigCal = bigPanel.getRoles().get(player.getUid());
			playerBigCal.setWinScore(playerBigCal.getWinScore() + score);
		}
		//检查是否大赢家
		checkBigWinner(bigPanel);
	}
	
	/**
	 * 检查是否大赢家
	 * @param bigPanel 大结算面板
	 */
	public void checkBigWinner(MjBigPanel bigPanel) {
		long maxWin = 0;
		Collection<PlayerBigCal> values = bigPanel.getRoles().values();
		for (PlayerBigCal calRole3 : values) {
			calRole3.setBigWinner(false);
		}
		for (PlayerBigCal calRole3 : values) {
			if (calRole3.getWinScore() > maxWin) {
				maxWin = calRole3.getWinScore();
			}
		}
		for (PlayerBigCal calRole3 : values) {
			if (calRole3.getWinScore() == maxWin) {
				calRole3.setBigWinner(true);
			}
		}
	}
	
}
